package composite

import "fmt"

// Component 抽象的组件对象，为组合中的对象声明接口，实现接口的缺省行为
type Component interface {
	// SomeOperation 示意方法，子组件对象可能有的功能方法
	SomeOperation(pre string)
	// AddChild 向组合对象加入组件对象
	AddChild(child Component)
	// RemoveChild 从组合对象中移除某个组件对象
	RemoveChild(child Component)
	// GetChildren 返回某个索引对应的组件对象
	GetChildren(index int) Component
}

// Composite 组合对象，通常需要存储子对象，定义有子部件的部件行为
// 并实现在Component里面定义的与子部件有关的操作
type Composite struct {
	// 用来存储组合对象中包含的子组件对象
	childComponents []Component
	name            string
}

func NewComposite(name string) Component {
	return &Composite{
		childComponents: make([]Component, 0),
		name:            name,
	}
}

// SomeOperation 示意方法，通常在里面需要实现递归的调用
func (c *Composite) SomeOperation(pre string) {
	fmt.Printf("%s+%s\n", pre, c.name)
	pre += " "
	for _, child := range c.childComponents {
		child.SomeOperation(pre)
	}
}

func (c *Composite) AddChild(child Component) {
	c.childComponents = append(c.childComponents, child)
}

func (c *Composite) RemoveChild(child Component) {
	idx := 0
	for i := 0; i < len(c.childComponents); i++ {
		if c.childComponents[i] != child {
			c.childComponents[idx] = c.childComponents[i]
			idx++
		}
	}
	c.childComponents = c.childComponents[:idx]
}

func (c *Composite) GetChildren(index int) Component {
	if len(c.childComponents) > 0 {
		if index >= 0 && index < len(c.childComponents) {
			return c.childComponents[index]
		}
	}
	return nil
}

// Leaf 叶子对象，叶子对象不再包含其他子对象
type Leaf struct {
	Component
	name string
}

// SomeOperation 示意方法，叶子对象可能有自己的功能方法
func (l *Leaf) SomeOperation(pre string) {
	// do something
	fmt.Printf("%s+%s\n", pre, l.name)
}

func NewLeaf(name string) Component {
	return &Leaf{
		name: name,
	}
}
